Next, we will examine daemons. Daemons are evaluated when any fact used by them is asserted. They provide a mechanism for asserting facts based on the assertion of other facts. In other words, if a fact is asserted that implies the state of other facts, these other facts can be asserted via a daemon. Daemons appear much like rules but, unlike rules, a daemon will evaluate facts as they are at the time that the daemon is examined. The inference engine will never attempt to assert a fact while processing a daemon, as it will when processing a rule while backward chaining. Neither will it examine rules using a fact set by a daemon the way that it will for facts set by rules when forward chaining. Thus, daemons do not affect the search strategy of the inference engine directly, the way that rules do. Instead, the inference engine will cease evaluating the daemon when it encounters a fact that is not asserted and will only examine other daemons when the daemon being processed asserts a fact.
The logic for daemons can be expressed as follows:
process daemons(fact)
set pointer to top of rule base
while daemons remain
get next daemon
if daemon uses fact then
evaluate daemon
if daemon evaluates true then
if daemon asserts new fact then
assert fact
process daemons(new fact)
end if
end if
end if
end while
end daemon
Note that the call to "process daemons" within the routine "process daemons" is a recursive call and that it passes in the newly asserted fact. The system will process daemons using a fact when that fact is asserted, regardless of how the fact was asserted. However, even when forward chaining, the system will not process rules using a fact when that fact is asserted by a daemon.
We will now set up an example with daemons. You may walk through this example using the shell. Go to the "tutorial shell" card. Click on the "load RB" button to make certain that the rule base is loaded in the "Rule Base" field. Next if the "Forward Chain/Backward Chain" field does not show "Backward Chain", click on it to toggle it to "Backward Chain".
Now modify the rule base as follows:
Add a query for the fact "car" as shown below.
fact
car
"the vehicle is a car, true or false?",
passengers
"How many passengers can it carry?",
wheels
"How many wheels does it have",
"used for cargo"
"Is it used to carry cargo?",
make
"What is the make of the vehicle?"
The query for fact "car" will wrap in the "Rule Base" field on the "tutorial shell" card. You should let it wrap. DO NOT place a carriage return inside of the quotes.
Then add the rule "truck" and daemons "cargo 1" and "cargo 2."
rule truck
if
fact wheels >= 4 and
fact "used for cargo" = yes
then
put "truck" into fact model
conclude "The vehicle is a truck."
daemon "cargo 1"
when
not fact car
then
put yes into fact "used for cargo"
daemon "cargo 2"
when
fact car
then
put no into fact "used for cargo"
If you would like to monitor the process, click on the "trace" check box to set trace on (an X will show in the box when it is on). To step through the process, click on the "step" check box to set step on (an X will show in the box when it is on).
Next, click on the "(re)start" button to start the session and answer the questions or follow the directions as they appear in the "Query" field. You should enter "model" in response to the "Enter goal..." query. During the session you may toggle between this card and others in the stack. The shell will retain its state when you toggle among cards; you do not have to start over each time that you return to the shell.
If you checked both trace and step, watch the "Trace" field to see the actions taken by the system. The system will show the state of the stack in the "Stack" field and the facts and their values in the "Facts" field.
When the system asks whether the vehicle is a car, answer "false". The system then asserts fact "car" and pushes fact "car" on the stack for daemon processing. Fact "car" now appears on the stack twice; once for processing the fact and once for processing the daemons using that fact.
The first daemon using "car" is daemon "cargo 1", which is also pushed on the stack. Since fact "car" is false, the daemon proves true and the system asserts fact "used for cargo" as "yes". Fact "used for cargo" is then pushed on the stack to process daemons using it. Since there are no daemons using fact "used for cargo", it is popped from the stack. Since daemon "cargo 1" is finished, it is also popped from the stack.
The system then resumes the search for daemons using fact "car", finds daemon
"cargo 2", pushes it on the stack, and evaluates it. Since fact "car" is false, this daemon proves false and nothing is asserted. The daemon is then popped from the stack. After all of the daemons are processed, fact "car" for processing daemons is popped from the stack. Since, fact "car" has been asserted, it is also popped from the stack.
The system completes rule "Corvette" and progresses through rules "Camaro", and
"Mustang" finding none of the rules true. When it reaches rule "truck", it will first ask about fact "wheels" by prompting "How many wheels does it have?" Answer "4". The system will then assert fact "wheels = 4", find the clause about wheels true and examine the clause using the fact "used for cargo". It finds that fact "used for cargo" is set to "yes" (as set by the daemon), causing that clause and the rule to prove true. It then asserts fact "model" and concludes "The vehicle is a truck.".
Now, retry the sequence, only this time answer "true" to the question "The vehicle is a car, true or false?" You will see that the system again processes daemon "cargo 1" when fact car is set, only this time the daemon fails to prove true. The system then processes daemon "cargo 2" and, since fact "car" is set to "true", the daemon proves true and fact "used for cargo" is set to "no".
The system then resumes processing rule "Corvette" and processes rules "Camaro" and "Mustang" until it finds one of them true. If it gets to rule "truck", it finds that rule false because fact "used for cargo" was set to "no" by the daemon "cargo 2".
Daemons operate the same whether you are forward or backward chaining. That is, they are evaluated any time that a fact used by them is asserted, regardless of how the fact was asserted or what value was assigned to it. Note that in the above example, we use fact "wheels" to force the system to examine rule "truck" when forward chaining. Otherwise, the system would never examine the rule since the fact "used for cargo" was established by a daemon rather than via query or another rule.
Feel free to modify the rule base on the "tutorial shell" card and experiment with daemons. If you wish to restore the original sample rule base, simply click on the "load RB" button.